#include "i2c_drv.h"  
#include "main.h"

GPIO_InitTypeDef GPIO_InitStruct = {0};

void _NOP(){  
 volatile int i = 640;  
 for(;i;--i);  
}  
  
  
  
extern GPIO_InitTypeDef GPIO_InitStructure;  
  
// SCL -------------------------------------------------------------------------  
void SCL_DIR(char state)  {  
 if(state) {
    GPIO_InitStruct.Pin = I2C_SCL_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(I2C_SCL_GPIO_Port, &GPIO_InitStruct);
  }  
  else {  
    GPIO_InitStruct.Pin = I2C_SCL_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(I2C_SCL_GPIO_Port, &GPIO_InitStruct);
  }  
}  
  
void SCL_OUT(char state) {  
  if(state) {  
      HAL_GPIO_WritePin(I2C_SCL_GPIO_Port, I2C_SCL_Pin, GPIO_PIN_SET);
  }  
  else {  
      HAL_GPIO_WritePin(I2C_SCL_GPIO_Port, I2C_SCL_Pin, GPIO_PIN_RESET);
  }  
}  
  
  
  
// SDA -------------------------------------------------------------------------  
void SDA_DIR(char state)  {  
  if(state) {
    GPIO_InitStruct.Pin = I2C_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(I2C_SDA_GPIO_Port, &GPIO_InitStruct);
  }  
  else {  
    GPIO_InitStruct.Pin = I2C_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(I2C_SDA_GPIO_Port, &GPIO_InitStruct);
  }   
}  
  
void SDA_OUT(char state) {  
  if(state) {  
      HAL_GPIO_WritePin(I2C_SDA_GPIO_Port, I2C_SDA_Pin, GPIO_PIN_SET);
  }  
  else {  
      HAL_GPIO_WritePin(I2C_SDA_GPIO_Port, I2C_SDA_Pin, GPIO_PIN_RESET);
  }  
}  
  
char SDA_IN(void) {  
   if((HAL_GPIO_ReadPin(I2C_SDA_GPIO_Port, I2C_SDA_Pin)) == GPIO_PIN_SET)  
     return 1;  
   else  
     return 0;  
}  
  
#define SCL_HIGH  SCL_OUT(1);  
#define SCL_LOW   SCL_OUT(0);  
#define SDA_HIGH  SDA_OUT(0);  
#define SDA_LOW   SDA_OUT(1);  
  
  
  
/****************************************************************************/  
/*  Initialize I2C interface                                                */  
/*  Function : Hrd_I2C_Init                                                 */  
/*      Parameters                                                          */  
/*          Input   :   Nothing                                             */  
/*          Output  :   Nothing                                             */  
/****************************************************************************/  
void Hrd_I2C_Init(){  
  SCL_OUT(0);  
  SCL_DIR(1);  
  SDA_DIR(1);  
  SDA_OUT(0);  
}  
  
  
/****************************************************************************/  
/*  Start Conditional for I2C                                               */  
/*  Function : Hrd_I2C_StartCond                                            */  
/*      Parameters                                                          */  
/*          Input   :   Nothing                                             */  
/*          Output  :   Nothing                                             */  
/****************************************************************************/  
void Hrd_I2C_StartCond(){  
  SDA_DIR(1);
  SCL_LOW;  
  _NOP();  
  SDA_HIGH;  
  _NOP();  
  SCL_HIGH;  
  _NOP();  
  SDA_LOW;  
  _NOP();  
  SCL_LOW;  
}  
  
  
/****************************************************************************/  
/*  Stop Conditional for I2C                                                */  
/*  Function : Hrd_I2C_StopCond                                             */  
/*      Parameters                                                          */  
/*          Input   :   Nothing                                             */  
/*          Output  :   Nothing                                             */  
/****************************************************************************/  
void Hrd_I2C_StopCond(){  
  SDA_DIR(1);
  SCL_LOW;  
  SDA_LOW;  
  _NOP();  
  SCL_HIGH;  
  _NOP();  
  SDA_HIGH;  
}  
  
  
/****************************************************************************/  
/*  Write Byte to I2C                                                       */  
/*  Function : Hrd_I2C_WriteByte                                            */  
/*      Parameters                                                          */  
/*          Input   :   character to write                                  */  
/*          Output  :   acknowledge                                         */  
/****************************************************************************/  
I2C_AKN_DEF Hrd_I2C_WriteByte  (unsigned char ch){  
  
  unsigned int i = 0;  
  SDA_DIR(1);
  for(i = 8; i; --i)  
  {  
    SCL_LOW;  
    if(ch&0x80) {  
      SDA_HIGH;  
    }  
    else {  
      SDA_LOW;  
    }  
    ch = ch << 1;
    _NOP();  
    SCL_HIGH;  
    _NOP();  
    SCL_LOW;  
  }  
  SDA_HIGH;  
  _NOP();  
  SCL_HIGH;  
  _NOP();  
  SDA_DIR(0);
  i = SDA_IN() ? I2C_NAK: I2C_AKN;  
  SCL_LOW;  
  return((I2C_AKN_DEF)i);  
}  
  
  
/****************************************************************************/  
/*  Read Byte from I2C                                                      */  
/*  Function : Hrd_I2C_ReadByte                                             */  
/*      Parameters                                                          */  
/*          Input   :   need acknowledge                                    */  
/*          Output  :   read character                                      */  
/****************************************************************************/  
unsigned char Hrd_I2C_ReadByte (I2C_AKN_DEF  Akn){  
  
  unsigned char ch =0;  
  unsigned int i = 0; 
  SDA_HIGH;
    SDA_DIR(0);
  
  for(i = 8; i; --i)  
  {  
    SCL_HIGH;  
    _NOP(); 
    ch = ch << 1;
    ch |= SDA_IN() ? 1:0;  
    SCL_LOW;  
    _NOP(); 
  }  
  SDA_DIR(1);
  if (Akn) SDA_LOW;  
  
  SCL_HIGH;  
  _NOP();  
  SCL_LOW;  
  
  return ch;  
}  

int i2c_master_tr(uint8_t addr, uint8_t* data, uint8_t size){
    int err = 0;
    Hrd_I2C_StartCond();
    if(Hrd_I2C_WriteByte(addr) == I2C_AKN){
        uint8_t i=0;
        for(i=0; i<size; i++){
            if(Hrd_I2C_WriteByte(data[i]) == I2C_AKN){
                continue ;
            }else{
                break ;
            }
        }
        if(i < size){
            err = -1;
        }else{
            err = 0;
        }
    }else{
        err = -2;
    }
    Hrd_I2C_StopCond();
    return err;
}

int i2c_master_rd(uint8_t addr, uint8_t* data, uint8_t size){
    int err = 0;
    Hrd_I2C_StartCond();
    if(Hrd_I2C_WriteByte(addr) == I2C_AKN){
        for(uint8_t i=0; i<size; i++){
            data[i] = Hrd_I2C_ReadByte(I2C_AKN);
        }
    }else{
        err = -1;
    }
    Hrd_I2C_StopCond();
    return err;
}





